package com.seashop.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.seashop.response.ResponseBase;
import com.seashop.constant.BaseConstant;
import com.seashop.constant.ComponentConstant;
import com.seashop.constant.RedisConstant;
import com.seashop.util.EncryptUtil;
import com.seashop.util.RandomListUtil;
import com.seashop.vo.AppHomeConfigVO;
import com.seashop.entity.AppHomeConfig;
import com.seashop.enums.LanguageTypeEnum;
import com.seashop.enums.PlatformEnum;
import com.seashop.feign.ProductFeignClient;
import com.seashop.feign.ThirdFeignClient;
import com.seashop.request.GoogleTransRequestParam;
import com.seashop.request.RecommendProductRequestParam;
import com.seashop.service.IAppHomeConfigService;
import com.seashop.util.BeanCopyUtil;
import com.seashop.redis.RedisZero;
import com.seashop.vo.ProductSimpleVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotBlank;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * App主页配置 前端控制器
 * </p>
 *
 * @author moredln
 * @since 2020-08-10
 */
@RestController
@RequestMapping("/appHome")
@Api(tags = "APP首页")
public class AppHomeConfigController {

    @Autowired
    private IAppHomeConfigService appHomeConfigService;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private ThirdFeignClient thirdFeignClient;
    @Autowired
    private RedisZero redisZero;

    @GetMapping("/getHomeConfig")
    @ApiOperation("获取首页配置信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "国家编码(TH:泰国;IN:印尼;ZH:中国;US:美国;UR:巴基斯坦;)", name = "countryCode", dataType = "string", required = true),
            @ApiImplicitParam(value = "平台(ios、android、wap)", name = "platform", dataType = "string", required = true),
            @ApiImplicitParam(value = "语言类型(TH:泰文;IN:印尼文;ZH:中文;EN:英文)", name = "languageType", dataType = "string", required = true),
            @ApiImplicitParam(value = "用户ID", name = "userId", dataType = "long", required = true)
    })
    public ResponseBase getHomeConfig(@NotBlank String countryCode, @NotBlank String platform, @Autowired String languageType, @NotBlank Long userId) {
        String redisKey = countryCode + "_" + RedisConstant.APP_HOME_CONFIG_INFO;
        if (redisZero.exists(redisKey)) {
            Object result = redisZero.get(redisKey);
            return ResponseBase.success(result);
        }
        AppHomeConfig appHomeConfig = appHomeConfigService.getOne(new QueryWrapper<AppHomeConfig>().select("`key`,`name`,`desc`,content,country_code,create_date").eq("country_code", countryCode));

        AppHomeConfigVO appHomeConfigVO = BeanCopyUtil.copy(appHomeConfig, AppHomeConfigVO.class);
        changeResponseBase(appHomeConfigVO, countryCode, platform, languageType, userId);
        appHomeConfigVO.setNewCustomers(redisZero.get("SYS_NEW_CUSTOMERS_ID"));
        appHomeConfigVO.setRecommendedShop(redisZero.get("SYS_NEW_CUSTOMERS_ID"));
        redisZero.set(redisKey, appHomeConfigVO);
        return ResponseBase.success(appHomeConfigVO);
    }

    @GetMapping("/listRecommendProductPage")
    @ApiOperation("推荐商品列表")
    public ResponseBase listRecommendProductPage(RecommendProductRequestParam param) {
        return productFeignClient.listRecommendProductPage(param);
    }

    /**
     * 重新封装首页配置信息
     *
     * @param appHomeConfigVO
     * @param countryCode
     * @param userId
     */
    private void changeResponseBase(AppHomeConfigVO appHomeConfigVO, String countryCode, String platform, String languageType, Long userId) {
        if (null == appHomeConfigVO) {
            return;
        }
        String content = appHomeConfigVO.getContent();
        if (StringUtils.isBlank(content)) {
            return;
        }
        boolean isApp = false;
        if (platform.equals("ios") || platform.equals("android")) {
            isApp = true;
        }
        JSONArray jsonArray = JSON.parseArray(content);
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String componentName = jsonObject.getString("componentName");
            //格式化COMPONENT_NAME_GOODS组件
            if (ComponentConstant.GOODS.equals(componentName)) {
                JSONArray data = jsonObject.getJSONArray("data");
                for (int j = 0; j < data.size(); j++) {
                    JSONObject dataJSONObject = data.getJSONObject(j);
                    String title = thirdFeignClient.batchTrans(new GoogleTransRequestParam(Arrays.asList(dataJSONObject.getString("title")), LanguageTypeEnum.EN.getName(), languageType.toLowerCase()));
                    dataJSONObject.put("title", title);
                    String sortBy = dataJSONObject.getString("sortBy");
                    JSONArray array = dataJSONObject.getJSONArray("data");
                    List<Map> productMap = new ArrayList<>();
                    for (int k = 0; k < array.size(); k++) {
                        JSONObject arrayJSONObject;
                        try {
                            arrayJSONObject = array.getJSONObject(k);
                            String productId = arrayJSONObject.getString("productId");
                            String productPlatform = arrayJSONObject.getString("platform");
                            if (PlatformEnum.SEASHOP.getCode().equals(productPlatform)) {
                                Integer[] ids = new Integer[]{Integer.valueOf(productId)};
                                List<ProductSimpleVO> ProductSimpleVOs = productFeignClient.queryProductSimpleInfo(ids, countryCode, languageType);
                                if (!ProductSimpleVOs.isEmpty()) {
                                    ProductSimpleVO productSimpleVO = ProductSimpleVOs.get(0);
                                    Map<String, Object> map = changeProductSimpleVOToMap(productSimpleVO);
                                    productMap.add(map);
                                }
                            }
                            if (PlatformEnum.SHOPEE.getCode().equals(productPlatform)) {
                                JSONObject shopeeExternalProduct = productFeignClient.getExternProductDetail(productId, PlatformEnum.SHOPEE.getCode(), countryCode, languageType, userId);
                                if (null != shopeeExternalProduct) {
                                    Map<String, Object> map = changeJsonObjectToMap(shopeeExternalProduct);
                                    productMap.add(map);
                                }
                            }
                            if (PlatformEnum.LAZADA.getCode().equals(productPlatform)) {
                                JSONObject lazadaProduct = productFeignClient.getExternProductDetail(productId, PlatformEnum.LAZADA.getCode(), countryCode, languageType, userId);

                                if (null != lazadaProduct) {
                                    Map<String, Object> map = changeJsonObjectToMap(lazadaProduct);
                                    productMap.add(map);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            Integer productId = array.getInteger(k);
                            Integer[] ids = new Integer[]{productId};
                            List<ProductSimpleVO> ProductSimpleVOs = productFeignClient.queryProductSimpleInfo(ids, countryCode, languageType);
                            if (!ProductSimpleVOs.isEmpty()) {
                                ProductSimpleVO productSimpleVO = ProductSimpleVOs.get(0);
                                Map<String, Object> map = changeProductSimpleVOToMap(productSimpleVO);
                                productMap.add(map);
                            }
                        }
                    }
                    if (ComponentConstant.GOODS_SORT_BY_RANDOM.equals(sortBy)) {
                        RandomListUtil.shuffle(productMap);
                    }
                    dataJSONObject.put("data", JSON.toJSON(productMap));
                }
                list.add(jsonObject);
                //翻译COMPONENT_NAME_QUICK_ENTRY组件
            } else if (ComponentConstant.QUICK_ENTRY.equals(componentName)) {
                List<JSONObject> listObject = new ArrayList<>();
                JSONArray data = jsonObject.getJSONArray("data");
                for (int j = 0; j < data.size(); j++) {
                    JSONObject dataJSONObject = data.getJSONObject(j);
                    String title = opTrans(dataJSONObject.getString("name"), LanguageTypeEnum.EN.getName(), languageType.toLowerCase());
                    dataJSONObject.put("name", title);
                    // 返回给APP的url要加上后缀参数
                    if (isApp && dataJSONObject.get("eventType").equals("url")) {
                        String url = (String) dataJSONObject.get("url");
                        if (!url.contains("?")) {
                            url += "?" + "from=opshop&countryCode=" + countryCode + "&languageType=" + languageType;
                        } else {
                            url += "&from=opshop&countryCode=" + countryCode + "&languageType=" + languageType;
                        }
                        dataJSONObject.put("url", url);
                    }
                    listObject.add(dataJSONObject);
                }
                jsonObject.put("data", listObject);
                list.add(jsonObject);
            } else if (ComponentConstant.PRODUCT_COLLECTION.equals(componentName)) {
                List<JSONObject> listObject = new ArrayList<>();
                JSONArray data = jsonObject.getJSONArray("data");
                for (int j = 0; j < data.size(); j++) {
                    JSONObject dataJSONObject = data.getJSONObject(j);
                    String title = thirdFeignClient.batchTrans(new GoogleTransRequestParam(Arrays.asList(dataJSONObject.getString("name")), LanguageTypeEnum.EN.getName(), languageType.toLowerCase()));
                    dataJSONObject.put("name", title);
                    listObject.add(dataJSONObject);
                    JSONArray dataJSONArray = dataJSONObject.getJSONArray("data");
                    redisZero.set(ComponentConstant.PRODUCT_COLLECTION_IDS + countryCode, dataJSONArray.toJSONString());
                }
                jsonObject.put("data", listObject);
                list.add(jsonObject);
            } else if (ComponentConstant.FEEDING_COLLECTION.equals(componentName)) {
                List<JSONObject> listObject = new ArrayList<>();
                JSONArray data = jsonObject.getJSONArray("data");
                for (int j = 0; j < data.size(); j++) {
                    JSONObject dataJSONObject = data.getJSONObject(j);
                    JSONArray dataJSONObjectJSONArray = dataJSONObject.getJSONArray("data");
                    RandomListUtil.shuffle(dataJSONObjectJSONArray);
                    listObject.add(dataJSONObject);
                }
                jsonObject.put("data", listObject);
                list.add(jsonObject);
            } else if (ComponentConstant.PRODUCT_SHARE.equals(componentName)) {
                List<Object> resultProduct = new ArrayList<>();
                List<Map> productList = new ArrayList<>();
                productList.addAll(queryTopShareInfo(jsonObject, countryCode, languageType));
                // 首页商品分享排行只显示9个
                List<Map> tempDataList = new ArrayList<>();
                for (int k = 0; k < productList.size(); k++) {
                    if (k < 9) {
                        tempDataList.add(productList.get(k));
                    }
                }
                resultProduct.addAll(tempDataList);
                jsonObject.put("data", resultProduct);
                list.add(jsonObject);
            } else {
                // 其它类型的广告位
                list.add(jsonObject);
            }
        }
        appHomeConfigVO.setContent(JSON.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect));
    }

    private List<Map> queryTopShareInfo(JSONObject jsonObject, String countryCode, String languageType) {
        List<Map> resultProduct = new ArrayList<>();
        List<Map> productList = new ArrayList<>();
        JSONArray data = jsonObject.getJSONArray("data");
        List<Integer> seashopIds = new ArrayList<>();
        List<Long> shopeeIds = new ArrayList<>();
        List<Long> lazadaIds = new ArrayList<>();
        for (int j = 0; j < data.size(); j++) {
            JSONObject dataJSONObject = data.getJSONObject(j);
            if (PlatformEnum.SHOPEE.getCode().equals(dataJSONObject.getString("platform"))) {
                shopeeIds.add(dataJSONObject.getLongValue("id"));
            } else if (PlatformEnum.LAZADA.getCode().equals(dataJSONObject.getString("platform"))) {
                lazadaIds.add(dataJSONObject.getLongValue("id"));
            } else {
                seashopIds.add(dataJSONObject.getIntValue("id"));
            }
        }
        Map<String, String> subTitleMap = new HashMap<>();
        Map<String, Integer> shareMap = new HashMap<>();
        for (int j = 0; j < data.size(); j++) {
            JSONObject dataJSONObject = data.getJSONObject(j);
            String pId = dataJSONObject.getString("id");
            subTitleMap.put(pId, dataJSONObject.getString("subTitle"));
            shareMap.put(pId, dataJSONObject.getInteger("fictitiousShare"));
        }

        if (CollectionUtils.isNotEmpty(seashopIds)) {
            Integer[] ids = seashopIds.toArray(new Integer[]{});
            List<ProductSimpleVO> ProductSimpleVOs = productFeignClient.queryProductSimpleInfoAndShare(ids, countryCode);
            if (null != ProductSimpleVOs && ProductSimpleVOs.size() > 0) {
                for (ProductSimpleVO ProductSimpleVO : ProductSimpleVOs) {
                    String subTitle = "";
                    Integer share = 0;
                    String productId = ProductSimpleVO.getProductId().toString();
                    subTitle = subTitleMap.get(productId);
                    if (null != ProductSimpleVO.getShare()) {
                        share = shareMap.get(productId) + ProductSimpleVO.getShare();
                    } else {
                        share = shareMap.get(productId);
                    }
                    Map map = new HashMap(12);
                    map.put("id", ProductSimpleVO.getProductId());
                    map.put("title", ProductSimpleVO.getTitle());
                    map.put("subTitle", subTitle);
                    map.put("price", ProductSimpleVO.getPrice());
                    map.put("priceMin", ProductSimpleVO.getPrice());
                    map.put("commissionShopkeeper", ProductSimpleVO.getCommissionShopkeeper());
                    map.put("commissionMember", ProductSimpleVO.getCommissionMember());
                    if (StringUtils.isNotEmpty(ProductSimpleVO.getPriceMarket())) {
                        map.put("priceMarket", ProductSimpleVO.getPriceMarket());
                    }
                    map.put("image", ProductSimpleVO.getImage());
                    map.put("share", share);
                    map.put("platform", "seashop");
                    productList.add(map);
                }
            }
        }
        resultProduct.addAll(productList);
        if (CollectionUtils.isNotEmpty(shopeeIds)) {
            String pids = shopeeIds.stream().map(s -> s.toString()).collect(Collectors.joining(","));
            JSONObject shopees = productFeignClient.getExternProductDetail(pids, PlatformEnum.SHOPEE.getCode(), countryCode, "en", null);
            JSONArray shopeeList = null;
            List<Map> shopeeListMap = shopeeList.toJavaList(Map.class);
            resultProduct.addAll(shopeeListMap);
        }
        if (CollectionUtils.isNotEmpty(lazadaIds)) {
            String pids = lazadaIds.stream().map(s -> s.toString()).collect(Collectors.joining(","));
            JSONObject lazadas = productFeignClient.getExternProductDetail(pids, PlatformEnum.LAZADA.getCode(), countryCode, "en", null);
            JSONArray lazadaList = null;
            List<Map> lazadaListMap = lazadaList.toJavaList(Map.class);
            resultProduct.addAll(lazadaListMap);
        }
        for (Map map : resultProduct) {
            if (PlatformEnum.SEASHOP.name().equals(map.get("platform")) || null == map.get("platform")) {
                continue;
            }
            Integer share = 0;
            String id = map.get("productId").toString();
            if (null != shareMap.get(id)) {
                share = shareMap.get(id);
            }
            map.put("share", share);
            map.put("subTitle", subTitleMap.get(id));
        }
        resultProduct.sort(new Comparator<Map>() {
            @Override
            public int compare(Map o1, Map o2) {
                if (null == o1.get("share") || null == o2.get("share")) {
                    return 0;
                }
                if ((Integer) (o1.get("share")) > (Integer) (o2.get("share"))) {
                    return -1;
                } else if ((Integer) (o1.get("share")) < (Integer) (o2.get("share"))) {
                    return 1;
                }
                return 0;
            }
        });
        return resultProduct;
    }

    private Map<String, Object> changeProductSimpleVOToMap(ProductSimpleVO productSimpleVO) {
        Map<String, Object> map = new HashMap<>(9);
        map.put("id", productSimpleVO.getProductId());
        map.put("title", productSimpleVO.getTitle());
        map.put("price", productSimpleVO.getPrice());
        map.put("commissionShopkeeper", productSimpleVO.getCommissionShopkeeper());
        map.put("commissionMember", productSimpleVO.getCommissionMember());
        map.put("priceMin", productSimpleVO.getPrice());
        if (StringUtils.isNotEmpty(productSimpleVO.getPriceMarket())) {
            map.put("priceMarket", productSimpleVO.getPriceMarket());
        }
        map.put("image", productSimpleVO.getImage());
        map.put("platform", PlatformEnum.SEASHOP.getCode());
        return map;
    }

    private Map<String, Object> changeJsonObjectToMap(JSONObject lazadaProduct) {
        JSONObject data = lazadaProduct.getJSONObject("data");
        Map<String, Object> map = new HashMap<>(9);
        map.put("id", data.getLongValue("id"));
        map.put("title", data.getString("title"));
        map.put("price", data.getString("salePrice"));
        JSONObject commissionList = data.getJSONObject("commissionList");
        map.put("commissionShopkeeper", commissionList.getString("commissionShopkeeper"));
        map.put("commissionMember", commissionList.getString("commissionMember"));
        map.put("priceMin", data.getString("salePrice"));
        if (StringUtils.isNotEmpty(data.getString("price"))) {
            map.put("priceMarket", data.getString("price"));
        }
        map.put("image", data.getString("imageLink"));
        map.put("platform", data.getString("platform"));
        return map;
    }

    /**
     * opshop自己的翻译工具 (先查本地数据库字典,没有才找翻译工具)
     *
     * @param text
     * @param fromLanguageType
     * @param toLanguageType
     * @return
     */
    public String opTrans(String text, String fromLanguageType, String toLanguageType) {
        if (StringUtils.isBlank(text)) {
            return text;
        }
        if (fromLanguageType.equals(toLanguageType)) {
            return text;
        }
        // 先去数据字典里面查找
        String result = productFeignClient.queryDictionary(text, fromLanguageType, toLanguageType);
        if (StringUtils.isBlank(result)) {
            String key = EncryptUtil.getInstance().MD5(text);
            // 先走redis缓存
            Object transRedis = redisZero.get(BaseConstant.TRANSLATE_PREFIX + key + fromLanguageType + toLanguageType);
            if (null != transRedis) {
                return transRedis.toString();
            }
            // 走接口翻译
            result = thirdFeignClient.googleTrans(text, fromLanguageType, toLanguageType);
            if (StringUtils.isNotBlank(result)) {
                redisZero.set(BaseConstant.TRANSLATE_PREFIX + key + fromLanguageType + toLanguageType, result);
            }
        }
        return result;
    }

}
